package lljson

import (
	"bytes"
	"reflect"
	"strings"
)

type ByteValue []byte

const (
	Reading = iota
	NotReading
)

type Unmarshal struct {
	v interface{}
}

type BeginDeserialize struct {
	json string
	v    interface{}
}

//将一个{}转为map[string]string
type desBegin struct {
	s        string //s就是那个json字符串
	jsonByte []byte //要处理的字节

	cache []byte //缓冲字节

	WorkMod uint

	UpBraceLevel  int //花括号等级
	MidBraceLevel int //中括号等级
}

// Deserialize 反序列化入口
func Deserialize(jsonS string, v interface{}) error {
	jsonS = strings.Replace(jsonS, "null", "[]", -1)
	des := new(BeginDeserialize)
	des.json = jsonS
	des.v = v
	err := des.begin()
	return err
}

func (b *BeginDeserialize) begin() error {
	typeOf := reflect.TypeOf(b.v).Elem() //Elem简单理解为x一个*
	//valueOf := reflect.ValueOf(b.v).Elem() //传进来的是个地址，我们要区他的指针来拿到他的值
	valueOf := *b.ValueElem()
	if !b.IfStruct() {
		err := b.HandleUnStruct()
		return err
	}
	for i := 0; i < typeOf.NumField(); i++ {

		inValue := valueOf.Field(i)
		inValueKind := valueOf.Field(i).Kind()
		u := new(Unmarshal)
		u.v = b.v
		Sname := typeOf.Field(i).Tag.Get("json")
		if Sname == "" {
			Sname = typeOf.Field(i).Name
		}
		byteValue := u.GetJsonValue(b.json, Sname)

		switch inValueKind {
		case reflect.String:
			inValue.SetString(byteValue.string())

		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			inValue.SetInt(byteValue.int64())

		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
			inValue.SetUint(byteValue.uint())

		case reflect.Float64:
			inValue.SetFloat(byteValue.float64())

		case reflect.Struct:
			err := Deserialize(byteValue.string(), inValue.Addr().Interface()) //Addr逻辑上简单理解为加一个*
			if err != nil {
				return err
			}
		case reflect.Bool:
			inValue.SetBool(byteValue.bool())

		case reflect.Ptr:
			if byteValue.string() == "[]" {
				continue
			}

			OneStruct := reflect.New(inValue.Type().Elem()).Interface()
			err := Deserialize(byteValue.string(), OneStruct)
			if err != nil {
				return err
			}
			inValue.Set(reflect.ValueOf(OneStruct))

		case reflect.Slice:
			{ //这一块判断是否为空
				if byteValue.string() == "[]" || byteValue.string() == "" {
					continue
				}

				slice := DivideSlice(byteValue)
				if len(slice) == 0 {
					continue
				}
			}
			slice := DivideSlice(byteValue)
			TempStruct := reflect.New(typeOf.Field(i).Type).Elem() //切片的一个值类型的接口

			for _, vv := range slice {
				//切片的一个值类型的接口,与接口对应
				OneStructElem := reflect.New(reflect.TypeOf(inValue.Interface()).Elem())

				if OneStructElem.Elem().Kind() == reflect.Ptr {
					//reflect.New里面必须是一个非指针类型，他返回一个指向该类型的指针value
					//inValue.Type()在切片指针里是一个**类型
					OneStructElem = reflect.New(inValue.Type().Elem().Elem())
					OneStruct := OneStructElem.Interface()

					err := Deserialize(bytes2string(vv), OneStruct)
					if err != nil {
						return err
					}
					TempStruct = reflect.Append(TempStruct, reflect.ValueOf(OneStruct))
				} else { //是一个切片指针
					//reflect.New里面必须是一个非指针类型，他返回一个指向该类型的指针value
					//这里是一个额额
					OneStructElem = reflect.New(inValue.Type().Elem())
					OneStruct := OneStructElem.Interface()

					err := Deserialize(bytes2string(vv), OneStruct)
					if err != nil {
						return err
					}

					TempStruct = reflect.Append(TempStruct, reflect.ValueOf(OneStruct).Elem())
				}
			}
			inValue.Set(TempStruct)
		}

	}
	return nil
}

func DivideSlice(sliceS []byte) [][]byte {
	//以下两部去掉头尾的中括号

	sliceS = sliceS[1:]
	sliceS = sliceS[:len(sliceS)-1]
	up := 0
	min := 0

	bytess := bytes.FieldsFunc(sliceS, func(r rune) bool {
		if up == 0 && min == 0 {
			if r == ',' {
				return true
			}
		}
		switch r {
		case '{':
			up++
		case '}':
			up--
		case '[':
			min++
		case ']':
			min--
		}
		return false
	})

	return bytess
}

// GetJsonValue 将jsonSz中的key的val拿到
func (u *Unmarshal) GetJsonValue(jsonS string, key string) ByteValue {
	dBegin := new(desBegin)
	b := []byte(jsonS)

	index := bytes.Index([]byte(jsonS), []byte(key))

	//可以判断括号的级数是不是正常的key，key与val名字重合，key中字符属于另一个key中的字符
	if !rangeJsonToIndex(jsonS, index, 1, 0) || b[index-2] == ':' || b[index+len(key)] != '"' { //判断字段是否在第一级{}，避免重复
		b = append(b[0:index], b[index+len(key):]...) //把字符换掉为空
		return u.GetJsonValue(bytes2string(b), key)
	}

	dBegin.jsonByte = b[index+len(key)+2:]

	dBegin.WorkMod = NotReading
	cache := dBegin.HandleByte()
	////.Println("key-json", key, string(cache))
	return cache
}

func (d *desBegin) HandleByte() []byte {
	////.Println("desBegin.jsonByte", string(d.jsonByte))
	for _, v := range d.jsonByte {
		////.Println("大小括号：", d.UpBraceLevel, d.MidBraceLevel)
		switch v {
		case '"':
			if !d.symmetry() {
				d.addCache('"')
			} else if d.WorkMod == NotReading {
				d.WorkMod = Reading
			} else if d.WorkMod == Reading {
				return d.cache
			}
		case '{':
			d.UpBraceLevel++
			if !d.symmetry() { //不对称
				d.WorkMod = Reading
			}
			d.addCache('{')
		case '[':
			d.MidBraceLevel++
			if !d.symmetry() { //不对称
				d.WorkMod = Reading
			}
			d.addCache('[')
		case '}':
			d.UpBraceLevel--
			if !d.symmetry() && d.UpBraceLevel == -1 { //括号不对称且大括号等级等于0，说明最开始的不是{，而结尾有}
				////.Println("debug")
				return d.cache
			}
			if !d.symmetry() { //不对称
				d.WorkMod = Reading
			}
			d.addCache('}')
		case ']':
			d.MidBraceLevel--
			if !d.symmetry() { //不对称
				d.WorkMod = Reading
			}
			d.addCache(']')
		case ',':
			if d.symmetry() {
				return d.cache
			} else {
				d.addCache(',')
			}
		default:
			d.addCache(v)
		}
	}
	return d.cache
}

func (d *desBegin) addCache(b byte) {
	d.cache = append(d.cache, b)
}

// symmetry 括号是否对称，即{为0个，[为0个是返回true
func (d *desBegin) symmetry() bool {
	if d.UpBraceLevel == 0 && d.MidBraceLevel == 0 {
		return true
	}
	return false
}

func (d *desBegin) clearCache() {
	d.cache = make([]byte, 0)
}
